package com.cicoding.service;/**
 * Created by Intellij IDEA.
 * User:  Administrator
 * Date:  2024/6/4
 */


import com.cicoding.config.RscjaProperties;
import com.cicoding.config.Uf3sProperties;
import com.cicoding.config.UhfDevice;
import com.cicoding.config.WebSocket;
import com.cicoding.domian.KufangData;
import com.cicoding.entity.dto.Uf3sParam;
import com.cicoding.tcp.client.NettyClient;
import com.cicoding.utlis.JdbcUtils;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import com.uhf.api.cls.Reader;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.*;
import java.util.concurrent.*;

/**
 * @Author: 刘明
 * @Description:
 * @Date: 2024/6/4 15:34
 */
@Service
@Slf4j
public class Uf3sReaderService {


    private NettyClient client;

   // private List<NettyClient> clientList;

    private ConcurrentHashMap<String, NettyClient> clientList = new ConcurrentHashMap<>();

    private ScheduledExecutorService executor = Executors.newScheduledThreadPool(1);


    @Resource
    private Uf3sProperties uf3sProperties;
    /**
     * 初始化数据,之后的数据用来对比
     */
    public static Cache<String, Long> cache  = CacheBuilder.newBuilder()
            .maximumSize(8000) // 可以根据需求设置缓存大小限制，比如1000条记录
            .build();
    /**
     * 盘点到的标签
     */
    public static Cache<String, Long>  RFIDCache = CacheBuilder.newBuilder()
            .expireAfterWrite(3000, TimeUnit.MINUTES)
            .build();
    /**
     * 数据库数据
     */
    Cache<String, String>  sqlData = CacheBuilder.newBuilder()
            .build();

    @Value("${tcpService.IP}")
    private String tcpIP;

    @Value("${tcpService.prot}")
    private String tcpPort;

    @Value("${uf3s-reader.IP}")
    private String readerIP;

    @Value("${uf3s-reader.antArray}")
    private String antArray;

    @Value("${uf3s-reader.portNum}")
    private Integer portNum;

    @Value("${uf3s-reader.power}")
    private Integer power;

    @Value("${readerType}")
    private String readerType;

    private boolean isStart;

    public boolean isStart() {
        return isStart;
    }

    public void setStart(boolean start) {
        isStart = start;
    }

    @Resource
    private WebSocket webSocket;

    public static boolean flage;

    private ScheduledFuture<?> scheduledTask;

    /*
     * 功能描述:初始化  uf3s读写器
     * 1.初始化tcp客户端 准备发送
     * 2.设置自动模式回调地址
     * 3.设置天线功率
     * @param
     * @Return: void
     * @Author: 努阳
     * @Date: 2024/6/4 16:21
     */
   // @PostConstruct
    public void startClient() {
        //判断读写器 类型是否为uf3s
        if (!"uf3s".equals(readerType)) {
            return;
        }
        for (Uf3sProperties.Uh3sDevice uh3sDevice : uf3sProperties.getConfig()) {
            //初始化tcp客户端
            client = new NettyClient(uh3sDevice.getIP(), 8088);
            try {
                client.start();
            } catch (Exception e) {
                log.error("uf3s 连接异常");
                e.printStackTrace();
            }
            Uf3sParam getmodey = new Uf3sParam(2003, null);
            Boolean getmodeyMessage = client.sendMessage(getmodey.toJsonString());
            log.info("uf3s 获取自动模式:{}", getmodeyMessage);

            //设置自动模式回调地址
            Uf3sParam uf3sParam = new Uf3sParam(2004, new Uf3sParam.AutoModeBean(0, tcpIP, 1, tcpPort, 0, 1));
            Boolean sendMessage = client.sendMessage(uf3sParam.toJsonString());
            log.info("uf3s 设置自动模式回调地址:{}", sendMessage);

            //设置天线功率
            Hashtable<Integer, Integer> powerMap = new Hashtable<>();
            for (int i = 1; i <= uh3sDevice.getPortNum(); i++) {
                powerMap.put(i, power);
            }
            Uf3sParam setPower = new Uf3sParam(1012, new Uf3sParam.MsgBaseSetPower(powerMap));
            Boolean setPowerMessage = client.sendMessage(setPower.toJsonString());
            log.info("uf3s 设置天线功率:{}", setPowerMessage);
            clientList.put(uh3sDevice.getIP(),client);
            try {
                // 执行任务代码
                Thread.sleep(100); // 每秒钟检查一次
            } catch (InterruptedException e) {
                // 处理中断异常
                Thread.currentThread().interrupt(); // 清除中断状态
            }
        }

    }

    public void start() {
        for (Uf3sProperties.Uh3sDevice uh3sDevice : uf3sProperties.getConfig()) {
            Uf3sParam uf3sParam = new Uf3sParam(2005, new Uf3sParam.DynamicStart(antArray));
            NettyClient nettyClient = clientList.get(uh3sDevice.getIP());
            Boolean sendMessage = nettyClient.sendMessage(uf3sParam.toJsonString());
        }
    }

    public void stop() {
        for (Uf3sProperties.Uh3sDevice uh3sDevice : uf3sProperties.getConfig()) {
            Uf3sParam uf3sParam = new Uf3sParam(2006, null);
            NettyClient nettyClient = clientList.get(uh3sDevice.getIP());
            Boolean sendMessage = nettyClient.sendMessage(uf3sParam.toJsonString());
        }
       // Uf3sParam uf3sParam = new Uf3sParam(2006, null);
       // Boolean sendMessage = client.sendMessage(uf3sParam.toJsonString());
    }

    public void judgeOpen() {
        if (!client.checkChannelActive()){
            start();
        }
    }


    public  void query() throws Exception {
        Connection conn = JdbcUtils.getConnect();
        Statement stat = conn.createStatement();
        ResultSet rs = stat.executeQuery("select * from kufangxinxis");
        List<KufangData> list = new ArrayList<>();
        while (rs.next()) {
            sqlData.put(rs.getString("code"),rs.getString("name"));
        }
        JdbcUtils.close(conn, rs);
        // return list;
    }

    public void compareCachesAndPrintMessages(){
        Map<String, Long> cacheData = cache.asMap();
        //Map<String, Long> cacheData = NestedCacheExample.getFromNestedCacheData(IP).asMap();
        Map<String, Long> RFIDCacheData = RFIDCache.asMap();
        //Map<String, Long> RFIDCacheData = RFIDCacheExample.getFromNestedCacheData(IP).asMap();

        Iterator<Map.Entry<String, Long>> cacheIterator = cacheData.entrySet().iterator();
        while (cacheIterator.hasNext()) {
            Map.Entry<String, Long> entry = cacheIterator.next();
            String key = entry.getKey();
            if (!RFIDCacheData.containsKey(key)) {
                if (sqlData.asMap().containsKey(key)) {
                    String value = sqlData.getIfPresent(key);
                    System.out.println(key + " -  (出库) 工器具"+value);
                    webSocket.sendInfo(key + " -  (出库) 工器具"+value,"89");
                    cacheIterator.remove(); // Remove the data from cacheData
                }
            }
        }

        Iterator<Map.Entry<String, Long>> RFIDIterator = RFIDCacheData.entrySet().iterator();
        List<String> keysToAdd = new ArrayList<>();
        while (RFIDIterator.hasNext()) {
            Map.Entry<String, Long> entry = RFIDIterator.next();
            String key = entry.getKey();
            if (!cacheData.containsKey(key)) {
                if (sqlData.asMap().containsKey(key)) {
                    keysToAdd.add(key);
                    String value = sqlData.getIfPresent(key);
                    webSocket.sendInfo(key + " -  (入库) 工器具"+value,"89");
                    System.out.println(key + " -  (入库) 工器具"+value);
                }
            }
        }
        // System.out.println();

        String cache = "";

        for (Map.Entry<String, Long> entry : cacheData.entrySet()) {
            cache += entry.getKey() +" , ";
            // System.out.println("Tag: " + entry.getKey() + ", Value: " + entry.getValue());
        }
        String rfid = "";

        for (Map.Entry<String, Long> entry : RFIDCacheData.entrySet()) {
            rfid += entry.getKey() + " , ";
            //System.out.println("Tag: " + entry.getKey() + ", Value: " + entry.getValue());
        }

        System.out.println("\nRFID Cache Data: "+ cache);
        System.out.println("\nRFID rfid Data: "+ rfid);

        log.error("\nRFID Cache Data: {}", cache);
        log.error("RFID rfid Data: {}",rfid);
        // Add the new keys to cacheData
        for (String key : keysToAdd) {
            cacheData.put(key, System.currentTimeMillis());
        }
        try {
            //    webSocket.sendInfo("3333","89");
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        RFIDCache.invalidateAll();
    }

    private boolean isFirstExecution = true; // 添加标志以判断是否是第一次执行
    private boolean isTaskScheduled = false; // 添加标志以判断任务是否已经被调度

    /**
     * 当执行这个定时任务时，如果在倒计时期间再次被调用，会取消之前的定时任务。
     * 在取消之前的任务后，重新计划一个新的任务。
     * 在延迟之前执行一些操作，比如记录日志和发送 WebSocket 信息。
     * 在延迟期间执行一些其他操作，比如通过 startReader 方法启动读取器。
     * 在延迟结束后执行具体的延迟任务，如果 isFirstExecution 为 false，则执行额外的比较任务等。
     * 如果在倒计时期间再次调用这个方法，会取消之前的定时任务，并且只有当倒计时结束之后，才会执行 isFirstExecution 里面的方法。
     * @param delayInSeconds
     */
    private ScheduledFuture<?> previousTaskFuture; // 用于存储上一个任务的引用
    public void scheduleTaskWithDelayAndClose(int delayInSeconds) {
        flage = false;
        if (isTaskScheduled) {
            // 如果任务已经被调度，取消之前的任务并重新计时延迟
            scheduledTask.cancel(true);
        }

        scheduledTask = executor.schedule(() -> {
            try {
                // 在延迟之前执行关闭方法
                // System.out.println("执行关闭其他方法...");
                log.error("--------------开始盘点 ---------");
                webSocket.sendInfo("开始盘点", "89");

                //startReader(zebraUHF);
                start();

                // 延迟指定秒数后执行任务
                scheduledTask = executor.schedule(() -> {
                    // 执行需要延迟执行的任务
                    if (!isFirstExecution) { // 如果不是第一次执行，则执行比较任务
                        compareCachesAndPrintMessages();
                        // stopReadTags();
                       // stopRedAll();
                        stop();
                        webSocket.sendInfo("结束盘点", "89");
                    }
                    //  System.out.println("执行延迟任务...");

                }, delayInSeconds, TimeUnit.SECONDS);

                isFirstExecution = false; // 标记为不是第一次执行
                isTaskScheduled = true; // 标记任务已经被调度
            } catch (Exception e) {
                // 处理异常
                e.printStackTrace();
            }
        }, 0, TimeUnit.SECONDS);
    }


    public void scheduleTaskWithDelay(int delayInSeconds) {
        flage = true;
        executor.schedule(() -> {
            try {
                // 在延迟之前执行关闭方法
                // System.out.println("执行关闭其他方法...");
                //初始化的时候,如果有两个读写器需要都运行盘点
                //startReader(zebraUHFProperties.getConfigs().get(0));
                start();
                executor.schedule(() -> {
                    // 执行需要延迟执行的任务
                  //  stopRedAll();
                    stop();
                }, delayInSeconds, TimeUnit.SECONDS);
            } catch (Exception e) {
                // 处理异常
                e.printStackTrace();
            }
        }, 0, TimeUnit.SECONDS);
    }

}
